package com.ruoyi.system.service.api.patient.impl;

import com.ruoyi.common.constant.HttpStatusCusCode;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.system.domain.api.patient.*;
import com.ruoyi.system.mapper.api.patient.GroupApiMapper;
import com.ruoyi.system.mapper.api.patient.GroupMemberApiMapper;
import com.ruoyi.system.mapper.api.patient.PatientInfoApiMapper;
import com.ruoyi.system.mapper.api.patient.RelationshipApiMapper;
import com.ruoyi.system.service.ISysDictDataService;
import com.ruoyi.system.service.api.patient.IGroupApiService;
import com.ruoyi.system.service.api.patient.IPatientApiService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

import static com.ruoyi.system.util.CommonUtils.CurrentTime;

/**
 * 分组Service业务层处理
 * 
 * @author sergio
 * @date 2024-11-13
 */
@Service
public class GroupApiServiceImpl implements IGroupApiService
{
    @Autowired
    private GroupApiMapper groupApiMapper;
    @Autowired
    private IPatientApiService patientApiService;
    @Autowired
    private ISysDictDataService sysDictDataService;

    private static final Logger log = LoggerFactory.getLogger(GroupApiServiceImpl.class);
    @Autowired
    private GroupMemberApiMapper groupMemberApiMapper;
    @Autowired
    private RelationshipApiMapper relationshipApiMapper;


    /**
     * 查询分组
     * 
     * @param id 分组主键
     * @return 分组
     */
    @Override
    public GroupDto selectGroupById(Long id)
    {
        return groupApiMapper.selectGroupById(id);
    }

    /**
     * 查询分组列表
     * 
     * @param group 分组
     * @return 分组
     */
    @Override
    public List<GroupDto> selectGroupList(GroupDto group)
    {
        return groupApiMapper.selectGroupList(group);
    }


    /**
     * 通过医院ID和医生ID获取分组列表
     *
     * @param group 分组
     * @return 分组集合
     */
    @Override
    public List<GroupDto> selectGroupListByDocId(GroupDto group)
    {
        // 判断医院ID和医生ID在医生信息表中是否存在(封禁和解散的不查)
        DoctorInfoDto doctorInfoDto = groupApiMapper.selectDoctorInfoByDocAHosId(group);
        if (doctorInfoDto == null) {
            log.info("查询医生信息警告:时间--{},医生ID:{}, 医院ID:{},信息:{}", CurrentTime(), group.getDoctorId(), group.getHosId(), "未找到相关医生信息");
            return new ArrayList<>();
        }
        group.setGroupType(Long.valueOf(sysDictDataService.selectDictDataById(149L).getDictValue()));
        return groupApiMapper.selectGroupListByDocId(group);
    }


    /**
     * 通过userId获取分组列表
     *
     * @param groupMember 分组
     * @return 分组集合
     */
    @Override
    public List<GroupMemberDto> selectGroupListByUserId(GroupMember groupMember)
    {
        // 先获取群成员所在的群组ID信息
        List<GroupMemberDto> groupMemberDtoList = groupMemberApiMapper.groupMemberListByUserId(groupMember);
        for (GroupMemberDto dto : groupMemberDtoList) {
            // 查询所在群组的所有群成员信息
            Long groupId = dto.getGroupId();
            GroupMember groupMember1 = new GroupMember();
            groupMember1.setGroupId(groupId);
            List<GroupMember> groupMemberList = groupMemberApiMapper.selectGroupMemberList(groupMember1);
            for (GroupMember groupMember2 : groupMemberList) {
                // 获取 userType 对应的字典值
                // 获取字典值并转换为 Integer
                Integer doctorUserType = Integer.valueOf(sysDictDataService.selectDictDataById(148L).getDictValue());
                Integer patientUserType = Integer.valueOf(sysDictDataService.selectDictDataById(147L).getDictValue());
                if (groupMember2.getUserType().equals(doctorUserType)) {
                    // user_type 为 doctor, 从 doctor_info 获取 im_id
                    String imId = groupMemberApiMapper.getDoctorImIdByUserId(groupMember2.getUserId());
                    groupMember2.setImId(imId);
                } else if (groupMember2.getUserType().equals(patientUserType)) {
                    // user_type 为 patient, 从 patient_info 获取 im_id
                    String imId = groupMemberApiMapper.getPatientImIdByUserId(groupMember2.getUserId());
                    groupMember2.setImId(imId);
                }

            }
            dto.setGroupMember(groupMemberList);
        }
        return groupMemberDtoList;
    }

    /**
     * 通过groupId获取分组详情和群成员
     *
     * @author sergio
     * @date 2024/11/18
     */
    @Override
    public GroupMemberDto selectGroupDetailByGroupId(Long groupId)
    {
        GroupMemberDto groupMemberDto = groupMemberApiMapper.groupMemberDetailByGroupId(groupId);
        List<GroupMember> groupMemberList = groupMemberDto.getGroupMember();
        for (GroupMember groupMember : groupMemberList) {
            if(groupMember.getUserType().equals(1)){
                // user_type 为 1，从 doctor_info 获取 im_id
                String imId = groupMemberApiMapper.getDoctorImIdByUserId(groupMember.getUserId());
                groupMember.setImId(imId);
            } else if(groupMember.getUserType().equals(2)){
                String imId = groupMemberApiMapper.getPatientImIdByUserId(groupMember.getUserId());
                groupMember.setImId(imId);
            }
        }
        groupMemberDto.setGroupMember(groupMemberList);
        return groupMemberDto;
    }

    /**
     * 获取可添加的分组成员
     *
     * @author sergio
     * @date 2024/11/18
     */

    @Override
    public List<PatientInfoDto> getPatientListByGroup(Long groupId)
    {
        // 先获取到该分组下已经存在的患者列表
        GroupMemberDto groupMemberDto =  groupMemberApiMapper.groupMemberDetailByGroupId(groupId);
        // todo 需要判断群组是否被禁用。不改也可以因为前端只能获取到未禁用或未解散的群组
        Long doctorId = groupMemberDto.getDoctorId();
        List<GroupMember> groupMemberList = groupMemberDto.getGroupMember();
        DoctorInfoDto doctorInfoDto = new DoctorInfoDto();
        RelationshipDto relationshipDto = new RelationshipDto();
        doctorInfoDto.setDoctorId(doctorId);
        relationshipDto.setDoctorInfo(doctorInfoDto);
        // 再获取到所有的已经绑定医患关系的患者列表
        RelationDao relationDao = new RelationDao();
        relationDao.setDoctorId(relationshipDto.DoctorInfo.getDoctorId());
        relationDao.setConsultation(sysDictDataService.selectDictDataById(141L).getDictValue());
        relationDao.setRelation(sysDictDataService.selectDictDataById(138L).getDictValue());
        relationDao.setBlocked(sysDictDataService.selectDictDataById(140L).getDictValue());
        List<PatientInfoDto> patientInfoDtoList = relationshipApiMapper.selectPatientInfoByDoctorId(relationDao);
        // 如果在groupMemberList中的userId存在patientInfoDtoList，那么说明已经入群了，所以设置isGrouped为1
        for (PatientInfoDto patientInfoDto : patientInfoDtoList) {
            for (GroupMember groupMember : groupMemberList) {
                if (groupMember.getUserId().equals(patientInfoDto.getPatientId())) {
                    patientInfoDto.setIsGrouped(1);
                }
            }
        }
        return patientInfoDtoList;
    }

    /**
     * 新增分组----医生主动创建分组
     *
     * @param group 分组
     * @return 结果
     */
    @Override
    @Transactional
    public GroupDto insertGroup(GroupDto group) {
        // 判断医院ID和医生ID在医生信息表中是否存在
        DoctorInfoDto doctorInfoDto = groupApiMapper.selectDoctorInfoByDocAHosId(group);
        if (doctorInfoDto == null) {
            log.info("查询医生信息警告信息:时间--{},医生ID:{}, 医院ID:{},信息:{}", CurrentTime(), group.getDoctorId(), group.getHosId(), "未找到相关医生信息");
            return null;  // 如果没有找到相关医生信息，返回 null 或者根据业务逻辑返回合适的值
        }

        group.setCreateTime(DateUtils.getNowDate());
        group.setCreateUser(doctorInfoDto.getUname());
        group.setUpdateUser(doctorInfoDto.getUname());

        // 插入群组
        groupApiMapper.insertGroup(group);
        Long generatedId = group.getId();
        if (generatedId <= 0) {
            throw new RuntimeException("插入群组失败");  // 插入失败时抛出异常，触发事务回滚
        }

        // 遍历插入群组成员
        List<GroupMember> groupMembers = group.getGroupMember();
        // todo 如果后期出现了将非医患绑定关系的患者加到群里的话，就需要增加判断分组成员是否属于医生绑定关系的逻辑。目前理论上是不会出现这个问题的。 因为给到前端的数据中只有绑定关系的患者
        // 额外将医生插入到群成员中
        GroupMember doctorGroupMember = new GroupMember();
        doctorGroupMember.setGroupId(group.getId());
        doctorGroupMember.setUserId(group.getDoctorId());
        // todo 这边只是考虑到医生创建分组的情况。后面需要考虑患者与患者之间创建分组的情况，到时候角色就得改变
        doctorGroupMember.setRole(sysDictDataService.selectDictDataById(145L).getDictValue());
        doctorGroupMember.setUserType(Integer.parseInt(sysDictDataService.selectDictDataById(148L).getDictValue()));
        groupMembers.add(doctorGroupMember);
        int membersInserted = 0;
        for (GroupMember member : groupMembers) {
            member.setGroupId(group.getId());
            int result = groupMemberApiMapper.insertGroupMember(member);  // 插入单个群组成员
            if (result > 0) {
                membersInserted++;
            } else {
                log.error("插入群组成员失败，成员ID:{}", member.getUserId());
                throw new RuntimeException("插入群组成员失败");  // 插入成员失败时抛出异常，触发事务回滚
            }
        }

        // 如果所有成员都成功插入，返回群组插入成功的数量
        if (membersInserted == groupMembers.size()) {
            return group;  // 返回群组插入的数量
        } else {
            throw new RuntimeException("部分群组成员插入失败");
        }
    }

    /**
     * 添加成员（二次添加）
     *
     * @author sergio
     * @date 2024/11/15
     */

    @Override
    public List<GroupMember> addGroupMember(GroupMemberDto groupMemberDto) {
        GroupDto groupDto = new GroupDto();
        // 判断是否存在群组（1启用 2封禁）
        groupDto.setGroupType(Long.valueOf(sysDictDataService.selectDictDataById(149L).getDictValue()));
        groupDto.setId(groupMemberDto.getGroupId());
        List<GroupDto> groupDtoList = groupApiMapper.selectGroupByGroupId(groupDto);
        if(groupDtoList.isEmpty()){
            log.info("查询分组信息警告信息:时间--{},医生ID:{}, 分组ID:{},信息:{}", CurrentTime(), groupMemberDto.getDoctorId(), groupMemberDto.getGroupId(), "该分组不存在或已被封禁");
            return null;
        }
        // todo 这边还需要添加判断该成员和医生是否为绑定关系,但是现在前端不可能传入非绑定关系的患者,所以暂时先不做修改
        List<GroupMember> groupMemberList = new ArrayList<>();
        // 首先判断入参中的成员ID和角色Type是否已经在分组成员表中。如果存在不添加，如果不存在则添加
        for (GroupMember groupMember : groupMemberDto.getGroupMember()) {
            // 循环添加群组成员
            groupMember.setGroupId(groupMemberDto.getGroupId());
            if (groupMemberApiMapper.groupMemberListByUserIdAGroupId(groupMember).isEmpty()){
                groupMember.setGroupId(groupMemberDto.getGroupId());
                groupMemberApiMapper.insertGroupMember(groupMember);
                groupMemberList.add(groupMember);
                log.info("插入群组成员成功，成员ID:{}", groupMember.getId());
            } else {
                log.info("群成员已存在，成员ID:{}", groupMember.getId());
            }
        }
        return groupMemberList;
    }

    @Override
    public int delGroupMember(GroupMemberDto groupMemberDto) {
        // 首先先判断操作人是否有权限进行移出成员，一般是管理员有权限
        GroupMember groupMember = new GroupMember();
        groupMember.setUserId(groupMemberDto.getUserId());
        groupMember.setGroupId(groupMemberDto.getGroupId());
        groupMember.setUserType(groupMemberDto.getUserType());
        GroupMember result = groupMemberApiMapper.groupMemberRoleByUserId(groupMember);
        if (result == null) {
            log.info("查询分组内用户信息警告信息:时间--{},用户ID:{}, 分组ID:{},信息:{}", CurrentTime(), groupMemberDto.getUserId(), groupMemberDto.getGroupId(), "该分组下用户不存在");
            return HttpStatusCusCode.GROUP_MEMBER_NOT_FOUND.getCode();
        }
        if(result.getRole().equals(sysDictDataService.selectDictDataById(145L).getDictValue())){
            // 判断前端传入的Id是否属于这个groupId下的，不能删除别人群组的id
            GroupMemberDto groupMemberDto1 = new GroupMemberDto();
            // 获取该分组ID下的所有用户
            groupMemberDto1 = this.selectGroupDetailByGroupId(groupMemberDto.getGroupId());
            List<GroupMember> groupMemberList = groupMemberDto.getGroupMember();
            int membersInserted = 0;
            // 创建一个新的 List 来存储相同的成员
            List<GroupMember> commonMembers = new ArrayList<>();
            // 这边是获取到前端传过来需要移出的成员ID。
            // 遍历 groupMemberList 和 groupMemberDto1.getGroupMember() 找到相同的成员
            for (GroupMember groupMember1 : groupMemberList) {
                for (GroupMember groupMember2 : groupMemberDto1.getGroupMember()) {
                    if (groupMember2.getId().equals(groupMember1.getId())) {
                        // 如果找到了相同的成员，添加到 commonMembers
                        commonMembers.add(groupMember1);
                        break; // 如果找到了相同成员，跳出内层循环
                    }
                }
            }

            if (commonMembers.size() < groupMemberDto.getGroupMember().size()) {
                log.info("查找分组内用户是否存在警告信息:时间--{},用户ID:{}, 分组ID:{},信息:{}", CurrentTime(), groupMemberDto.getUserId(), groupMemberDto.getGroupId(), "该群组下没有该用户");
                return HttpStatusCusCode.USER_MEMBER_NOT_IN_GROUP.getCode();
            }

            // 遍历 commonMembers，删除相应的成员
            for (GroupMember commonMember : commonMembers) {
                int size = groupMemberApiMapper.deleteGroupMemberById(commonMember.getId());
                if (size > 0) {
                    membersInserted++; // 成功删除的成员数量
                } else {
                    log.info("移出分组内用户信息警告信息:时间--{},ID:{}, 分组ID:{},信息:{}", CurrentTime(), commonMember.getId(), groupMemberDto.getGroupId(), "移出分组成员失败");
                    return HttpStatusCusCode.DEL_FAILED.getCode();
                }
            }
            return membersInserted;

        } else {
            log.info("查询分组内用户信息警告信息:时间--{},用户ID:{}, 分组ID:{},信息:{}", CurrentTime(), groupMemberDto.getUserId(), groupMemberDto.getGroupId(), "该用户无权移出分组成员");
            return HttpStatusCusCode.GROUP_MEMBER_NO_POWER.getCode();
        }

    }


    @Override
    public int outGroupMember(GroupMemberDto groupMemberDto) {
        // 首先先判断操作人存在于该分组
        GroupMember groupMember = new GroupMember();
        groupMember.setUserId(groupMemberDto.getUserId());
        groupMember.setGroupId(groupMemberDto.getGroupId());
        GroupMember result = groupMemberApiMapper.groupMemberRoleByUserId(groupMember);
        if (result == null) {
            log.info("查询分组内用户信息警告信息:时间--{},用户ID:{}, 分组ID:{},信息:{}", CurrentTime(), groupMemberDto.getUserId(), groupMemberDto.getGroupId(), "该分组下用户不存在");
            return HttpStatusCusCode.GROUP_MEMBER_NOT_FOUND.getCode();
        }
        // todo 如果是医生退出了群组,则解散该分组
        // ....

        return groupMemberApiMapper.deleteGroupMemberById(result.getId());


    }

    /**
     * 解散分组
     *
     * @author sergio
     * @date 2024/11/21
     */
    @Override
    public int disbandGroup(GroupDto groupDto) {
        GroupDto groupDto1 = new GroupDto();
        groupDto1.setId(groupDto.getId());
        // 设置状态为解散
        groupDto1.setGroupType(Long.valueOf(sysDictDataService.selectDictDataById(151L).getDictValue()));
        return groupApiMapper.updateGroup(groupDto1);
    }

    /**
     * 修改分组
     * 
     * @param group 分组
     * @return 结果
     */
    @Override
    public int updateGroup(GroupDto group)
    {
        group.setUpdateTime(DateUtils.getNowDate());
        return groupApiMapper.updateGroup(group);
    }

    /**
     * 批量删除分组
     * 
     * @param ids 需要删除的分组主键
     * @return 结果
     */
    @Override
    public int deleteGroupByIds(Long[] ids)
    {
        return groupApiMapper.deleteGroupByIds(ids);
    }

    /**
     * 删除分组信息
     * 
     * @param id 分组主键
     * @return 结果
     */
    @Override
    public int deleteGroupById(Long id)
    {
        return groupApiMapper.deleteGroupById(id);
    }
}
